import threading

import paramiko
import socket
import select

ssh_tunnel_status = 0

status_lock = threading.Lock()

def ssh_tunnel():
    global ssh_tunnel_status
    hostname = '106.53.100.120'
    port = 22
    username = 'sujianning'
    password = '19701975ASdf'
    local_port = 8060
    remote_host = 'localhost'
    remote_port = 8050
    try:
        # 创建SSH客户端
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(hostname, port, username, password)

        # 获取SSH的传输通道
        transport = client.get_transport()

        # 进行端口转发
        local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        local_socket.bind(('localhost', local_port))
        local_socket.listen(5)

        with status_lock:
            ssh_tunnel_status = 1
            print(ssh_tunnel_status)
            print(f"端口转发成功: localhost:{local_port} -> {remote_host}:{remote_port}")

        while True:
            client_socket, addr = local_socket.accept()
            print(f"连接来自: {addr}")
            # 通过SSH的传输通道进行端口转发
            channel = transport.open_channel('direct-tcpip', (remote_host, remote_port), client_socket.getpeername())
            forward(client_socket, channel)

    except Exception as e:
        with status_lock:
            ssh_tunnel_status = 2
        print(f"发生错误: {e}")
    finally:
        client.close()
        with status_lock:
            ssh_tunnel_status = 0
        print("SSH连接已关闭。")

def forward(local_sock, remote_channel):
    while True:
        # 使用select监听数据的可读状态
        r, _, _ = select.select([local_sock, remote_channel], [], [])
        if local_sock in r:
            data = local_sock.recv(1024)
            if len(data) == 0:
                break
            remote_channel.send(data)
        if remote_channel in r:
            data = remote_channel.recv(1024)
            if len(data) == 0:
                break
            local_sock.send(data)
    local_sock.close()
    remote_channel.close()

if __name__ == '__main__':
    ssh_tunnel()
